﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.IO;
using System.Collections.Generic;

namespace MyWebPagesStarterKit
{
    /// <summary>
    /// Summary description for RolesManagement
    /// </summary>
    public class RolesManagement : Persistable<RolesManagement.Data>
    {
        public RolesManagement(): base(){}

        public bool RoleExit(ISection section, string role, Rule rule)
        {
            List<SectionData> locatedObjects = _data.Sections.FindAll(delegate(SectionData s) { return s.SectionId == section.SectionId; });

            foreach (SectionData sd in locatedObjects)
            {
                if (sd.Role.Equals(role) && sd.Rule.Equals(rule))
                    return true;
            }
            return false;
        }

        private bool IsRoleUpdate(ISection section, string role)
        {
            SectionData locatedObject = _data.Sections.Find(delegate(SectionData s) { return s.SectionId == section.SectionId && s.Role == role; });

            if (locatedObject!=null)
                    return true;
            return false;
        }

     
        public void AddRole(ISection section, string role, Rule rule)
        {
            if (role.Equals("UnAuthenticated"))
            {
                SectionData locatedObject = _data.Sections.Find(delegate(SectionData s) { return s.SectionId == section.SectionId && s.Role == "UnAuthenticated"; });
                if(locatedObject!=null)
                    locatedObject.Rule = rule;
                else
                    _data.Sections.Add(new SectionData(section.SectionId, "UnAuthenticated", rule));
            }
            else
            {

                if (IsRoleUpdate(section, role))
                {
                    SectionData locatedObject = _data.Sections.Find(delegate(SectionData s) { return s.SectionId == section.SectionId && s.Role == role; });
                    if(locatedObject!=null)
                        locatedObject.Rule = rule;
                }
                else
                {
                    SectionData data = new SectionData(section.SectionId, role, rule);
                    _data.Sections.Add(data);
                }
            }
            SaveData();
        }

        public List<SectionData> SectionsData(ISection section)
        {
            return _data.Sections.FindAll(delegate(SectionData s) { return s.SectionId == section.SectionId; });
        }


        public bool Access(ISection section, Rule rule)
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                if (Roles.IsUserInRole("Administrators")) //Allways allow administrators
                    return true;

                foreach (SectionData sd in SectionsData(section))
                {
                    if (sd.Rule == rule && Roles.IsUserInRole(sd.Role))
                        return true;
                }
                return false;
            }
            else
            {
                SectionData locatedObject = _data.Sections.Find(delegate(SectionData s) { return s.SectionId == section.SectionId && s.Role == "UnAuthenticated"; });
                return (locatedObject.Rule == rule);
            }
        }


        /// <summary>
        /// Removes RoleData from a specific Role 
        /// </summary>
        /// <param name="section"></param>
        /// <param name="role"></param>
        public void DeleteRoleData(ISection section, string role)
        {
            List<SectionData> locatedObjects = _data.Sections.FindAll(delegate(SectionData s) { return s.SectionId == section.SectionId && s.Role==role; });
            if (locatedObjects != null)
            {
                _data.Sections.RemoveAll(delegate(SectionData s) { return s.SectionId == section.SectionId; });
                SaveData();
            }
        }

        /// <summary>
        /// Removes section RoleData
        /// </summary>
        /// <param name="section"></param>
        public void DeleteRoleData(ISection section)
        {
            List<SectionData> locatedObjects = _data.Sections.FindAll(delegate(SectionData s) { return s.SectionId == section.SectionId; });
            if (locatedObjects != null)
            {
                _data.Sections.RemoveAll(delegate(SectionData s) { return s.SectionId == section.SectionId; });
                SaveData();
            }
        }



        private static RolesManagement _instance;

        public static RolesManagement GetInstance()
        {
            if (_instance == null)
            {
                _instance = new RolesManagement();
                string dataFilePath = HttpContext.Current.Server.MapPath(_instance.GetDataFilename());

                if (File.Exists(dataFilePath))
                {
                    _instance.LoadData();
                }
            }
            return _instance;
        }

        protected override string GetDataFilename()
        {
            return "~/App_Data/SectionRolesData.config";
        }


        public class Data
        {
            public List<SectionData> Sections = new List<SectionData>();
        }


        [Serializable]
        public class SectionData
        {
            private string _SectionId;
            private string _Role;
            private Rule _Rule;

            public SectionData() { }

            public SectionData(string id)
            {
                this._SectionId = id;
            }

            public SectionData(string id, string role, Rule rule)
            {
                this._SectionId = id;
                this._Role = role;
                this._Rule = rule;
            }

            public string SectionId
            {
                get { return _SectionId; }
                set { _SectionId = value; }
            }

            public string Role
            {
                get { return _Role; }
                set { this._Role = value; }
            }

            public Rule Rule
            {
                get { return _Rule; }
                set { this._Rule = value; }
            }
        }
    }
}
